﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MoreDots.Rotations.Classes;
using ff14bot.Enums;
using ff14bot;
using MoreDots.SpellNames.Jobs;
using ff14bot.Managers;
using MoreDots.SpellNames.Classes;
using ff14bot.Helpers;
using ff14bot.Objects;

namespace MoreDots.Rotations.Jobs
{
    public class Monk : Pugilist
    {
        public override string Name { get { return "MoreDots [" + GetType().Name + "]"; } }
        public override ClassJobType[] Class { get { return new ClassJobType[] { ClassJobType.Monk }; } }

        #region Lower LvL Rotations
        public async override Task<bool> CombatLvL1()
        {
            return await BootshineCombo();
        }
        public async override Task<bool> CombatLvL2() { return await CombatLvL1(); }
        public async override Task<bool> CombatLvL4()
        {
            if (await Featherfoot()) return true;
            if (await BootshineCombo()) return true;

            return true;
        }
        public async override Task<bool> CombatLvL6() { return await CombatLvL4(); }
        public async override Task<bool> CombatLvL8()
        {
            if (await SecondWind()) return true;
            if (await Featherfoot()) return true;
            if (await BootshineCombo()) return true;

            return true;
        }
        public async override Task<bool> CombatLvL10() { return await CombatLvL8(); }
        public async override Task<bool> CombatLvL12()
        {
            if (await SecondWind()) return true;
            if (await Featherfoot()) return true;
            if (await MonkSpells.InternalRelease.Buff()) return true;
            if (await MonkSpells.Haymaker.Cast()) return true;
            if (await BootshineCombo()) return true;

            return true;
        }
        public async override Task<bool> CombatLvL14() { return await CombatLvL12(); }
        public async override Task<bool> CombatLvL16()
        {
            if (await SecondWind()) return true;
            if (await Featherfoot()) return true;
            if (await TouchOfDeath()) return true;
            if (await MonkSpells.InternalRelease.Buff()) return true;
            if (await MonkSpells.Haymaker.Cast()) return true;
            if (await BootshineCombo()) return true;

            return true;
        }
        public async override Task<bool> CombatLvL18()
        {
            if (await SecondWind()) return true;
            if (await Featherfoot()) return true;
            if (await TouchOfDeath()) return true;
            if (await MonkSpells.InternalRelease.Buff()) return true;
            if (await MonkSpells.Haymaker.Cast()) return true;
            if (await RaptorForm()) return true;
            if (await BootshineCombo()) return true;

            return true;
        }
        public async override Task<bool> CombatLvL20() { return await CombatLvL18(); }
        public async override Task<bool> CombatLvL22()
        {
            if (await FistsOfEarth()) return true;
            if (await SecondWind()) return true;
            if (await Featherfoot()) return true;
            if (await TouchOfDeath()) return true;
            if (await MonkSpells.InternalRelease.Buff()) return true;
            if (await MonkSpells.Haymaker.Cast()) return true;
            if (await MonkSpells.CrossClass.MercyStroke.Cast()) return true;
            if (await RaptorForm()) return true;
            if (await BootshineCombo()) return true;

            return true;
        }
        public async override Task<bool> CombatLvL24() { return await CombatLvL22(); }
        public async override Task<bool> CombatLvL26() { return await CombatLvL22(); }
        public async override Task<bool> CombatLvL28() { return await CombatLvL22(); }
        public async override Task<bool> CombatLvL30()
        {
            if (await FistsOfEarth()) return true;
            if (await SecondWind()) return true;
            if (await Featherfoot()) return true;
            if (await TouchOfDeath()) return true;
            if (await MonkSpells.InternalRelease.Buff()) return true;
            if (await MonkSpells.CrossClass.BloodForBlood.Buff()) return true;
            if (await MonkSpells.Haymaker.Cast()) return true;
            if (await MonkSpells.CrossClass.MercyStroke.Cast()) return true;
            if (await RaptorForm()) return true;
            if (await CoeurlForm()) return true;
            if (await BootshineCombo()) return true;

            return true;
        }
        public async override Task<bool> CombatLvL32() { return await CombatLvL30(); }
        public async override Task<bool> CombatLvL34() { return await CombatLvL30(); }
        public async override Task<bool> CombatLvL36() { return await CombatLvL30(); }
        public async override Task<bool> CombatLvL38()
        {
            if (await FistsOfEarth()) return true;
            if (await SecondWind()) return true;
            if (await Featherfoot()) return true;
            if (await TouchOfDeath()) return true;
            if (await MonkSpells.InternalRelease.Buff()) return true;
            if (await MonkSpells.CrossClass.BloodForBlood.Buff()) return true;
            if (await MonkSpells.Haymaker.Cast()) return true;
            if (await MonkSpells.CrossClass.MercyStroke.Cast()) return true;
            if (await RaptorForm()) return true;
            if (await CoeurlForm()) return true;
            if (await BootshineCombo()) return true;

            return true;
        }
        public async override Task<bool> CombatLvL40()
        {
            if (await FistsOfEarth()) return true;
            if (await FistsOfFire()) return true;
            if (await SecondWind()) return true;
            if (await Featherfoot()) return true;
            if (await TouchOfDeath()) return true;
            if (await MonkSpells.InternalRelease.Buff()) return true;
            if (await MonkSpells.CrossClass.BloodForBlood.Buff()) return true;
            if (await MonkSpells.Haymaker.Cast()) return true;
            if (await MonkSpells.SteelPeak.Cast()) return true;
            if (await MonkSpells.CrossClass.MercyStroke.Cast()) return true;
            if (await RaptorForm()) return true;
            if (await CoeurlForm()) return true;
            if (await BootshineCombo()) return true;

            return true;
        }
        public async override Task<bool> CombatLvL42()
        {
            if (await FistsOfEarth()) return true;
            if (await FistsOfFire()) return true;
            if (await SecondWind()) return true;
            if (await Mantra()) return true;
            if (await Featherfoot()) return true;
            if (await TouchOfDeath()) return true;
            if (await MonkSpells.InternalRelease.Buff()) return true;
            if (await MonkSpells.CrossClass.BloodForBlood.Buff()) return true;
            if (await MonkSpells.Haymaker.Cast()) return true;
            if (await MonkSpells.SteelPeak.Cast()) return true;
            if (await MonkSpells.CrossClass.MercyStroke.Cast()) return true;
            if (await RaptorForm()) return true;
            if (await CoeurlForm()) return true;
            if (await BootshineCombo()) return true;

            return true;
        }
        public async override Task<bool> CombatLvL44() { return await CombatLvL42(); }
        public async override Task<bool> CombatLvL46()
        {
            if (await FistsOfEarth()) return true;
            if (await FistsOfFire()) return true;
            if (await SecondWind()) return true;
            if (await Mantra()) return true;
            if (await Featherfoot()) return true;
            if (await TouchOfDeath()) return true;
            if (await MonkSpells.InternalRelease.Buff()) return true;
            if (await MonkSpells.CrossClass.BloodForBlood.Buff()) return true;
            if (await MonkSpells.Haymaker.Cast()) return true;
            if (await MonkSpells.SteelPeak.Cast()) return true;
            if (await MonkSpells.HowlingFist.Cast()) return true;
            if (await MonkSpells.CrossClass.MercyStroke.Cast()) return true;
            if (await RaptorForm()) return true;
            if (await CoeurlForm()) return true;
            if (await BootshineCombo()) return true;

            return true;
        }
        public async override Task<bool> CombatLvL48() { return await CombatLvL46(); }
        #endregion

        public async override Task<bool> CombatLvL50()
        {
            if (await FistsOfEarth()) return true;
            if (await FetterWard()) return true;
            if (await Mantra()) return true;
            if (await SecondWind()) return true;
            if (await Featherfoot()) return true;
            if (await Invigorate()) return true;
            if (await Enliven()) return true;
            if (await Somersault()) return true;
            if (await TouchOfDeath()) return true;
            if (await PerfectBalance()) return true;
            if (await MonkSpells.CrossClass.BloodForBlood.Buff()) return true;
            if (await MonkSpells.InternalRelease.Buff()) return true;
            if (await AxeKick()) return true;
            if (await MonkSpells.Haymaker.Cast()) return true;
            if (await MonkSpells.SteelPeak.Cast()) return true;
            if (await MonkSpells.HowlingFist.Cast()) return true;
            if (await MonkSpells.CrossClass.MercyStroke.Cast()) return true;
            if (await OpoOpoForm()) return true;
            if (await RaptorForm()) return true;
            if (await CoeurlForm()) return true;
            if (await BootshineCombo()) return true;
            if (await WeaponThrow()) return true;

            return true;
        }

        #region Combat Abilities
        #region Stances
        private async Task<bool> OpoOpoForm()
        {
            if (!Core.Player.HasAura("Opo-Opo Form"))
                return false;

            if (!Core.Player.HasAura(MonkSpells.DragonKick.Name, true, 3000))
                return await MonkSpells.DragonKick.Cast();

            return await MonkSpells.Bootshine.Cast();
        }
        private async Task<bool> RaptorForm()
        {
            if (!Core.Player.HasAura("Raptor Form"))
                return false;

            if (!Core.Player.HasAura(MonkSpells.TwinSnakes.Name, true, 5000) || Core.Player.CurrentTarget.IsBehind)
                return await MonkSpells.TwinSnakes.Cast();

            return await MonkSpells.TrueStrike.Cast();
        }
        private async Task<bool> CoeurlForm()
        {
            if (!Core.Player.HasAura("Coeurl Form"))
                return false;

            if (!Core.Player.HasAura(MonkSpells.Demolish.Name, true, 6000))
                return await MonkSpells.Demolish.Cast();

            if (Core.Player.CurrentTarget.IsFlanking)
                return await MonkSpells.SnapPunch.Cast();

            if (Core.Player.CurrentTarget.IsBehind)
                return await MonkSpells.Demolish.Cast();

            return await MonkSpells.Rockbreaker.Cast();
        }
        #endregion
        #region Combos
        private async Task<bool> BootshineCombo()
        {
            if (Core.Player.HasAura("Coeurl Form"))
                return await MonkSpells.SnapPunch.Cast();

            if (Core.Player.HasAura("Raptor Form"))
                return await MonkSpells.TrueStrike.Cast();

            return await MonkSpells.Bootshine.Cast();
        }
        #endregion
        #region Abilities
        private async Task<bool> FistsOfFire()
        {
            if (!Core.Player.HasAura(MonkSpells.FistsOfFire.Name) && Core.Player.CurrentHealthPercent >= 30)
                return await MonkSpells.FistsOfFire.Cast(Core.Player);

            return false;
        }
        private async Task<bool> FistsOfEarth()
        {
            if (!Core.Player.HasAura(MonkSpells.FistsOfEarth.Name) && (Core.Player.CurrentHealth < 30) || Core.Player.ClassLevel < 40)
                return await MonkSpells.FistsOfEarth.Cast(Core.Player);

            return false;
        }
        private async Task<bool> TouchOfDeath()
        {
            if (!Core.Player.CurrentTarget.HasAura(MonkSpells.TouchOfDeath.Name, true, 3000))
                return await MonkSpells.TouchOfDeath.Cast();

            return false;
        }
        private async Task<bool> PerfectBalance()
        {
            if (!Core.Player.HasAura(MonkSpells.PerfectBalance.Name))
                return await MonkSpells.PerfectBalance.Cast(Core.Player);

            if (Core.Player.HasAura(MonkSpells.PerfectBalance.Name))
            {
                if (!Core.Player.CurrentTarget.HasAura(MonkSpells.Demolish.Name))
                    return await MonkSpells.Demolish.Cast();

                if (!Core.Player.HasAura(MonkSpells.TwinSnakes.Name))
                    return await MonkSpells.TwinSnakes.Cast();

                return await MonkSpells.SnapPunch.Cast();
            }

            return false;
        }
        #endregion
        #region Defensive
        private async Task<bool> SecondWind()
        {
            if (Core.Player.CurrentHealthPercent < 50)
                return await MonkSpells.SecondWind.Buff();

            return false;
        }
        private async Task<bool> Mantra()
        {
            return false;
        }
        private async Task<bool> Invigorate()
        {
            if (Core.Player.CurrentTPPercent < 50)
                return await MonkSpells.CrossClass.Invigorate.Buff();

            return false;
        }
        private async Task<bool> Featherfoot()
        {
            if (Core.Player.CurrentHealthPercent < 60 && Core.Player.CurrentTarget.Location.Distance(Core.Player.Location) < 5)
                return await MonkSpells.Featherfoot.Buff();

            return false;
        }
        #endregion
        #region PVP
        private async Task<bool> AxeKick()
        {
            return await MonkSpells.PvP.AxeKick.Cast();
        }
        private async Task<bool> Somersault()
        {
            List<string> spells = new List<string> { ConjurerSpells.CureII.Name, ConjurerSpells.Medica.Name, ConjurerSpells.MedicaII.Name, ArcanistSpells.Physick.Name, ScholarSpells.Adloquium.Name };

            if (spells.Contains((Core.Player.CurrentTarget as BattleCharacter).SpellCastInfo.Name))
                return await MonkSpells.PvP.Somersault.Cast();

            return false;

        }
        private async Task<bool> WeaponThrow()
        {
            if (Core.Player.CurrentTarget.HasAura("Sprint"))
                return await MonkSpells.PvP.WeaponThrow.Cast();

            return false;
        }
        private async Task<bool> Enliven()
        {
            if (Core.Player.CurrentTPPercent < 50 && !Actionmanager.CanCast(MonkSpells.CrossClass.Invigorate.Name, Core.Player))
                return await MonkSpells.PvP.Enliven.Buff();

            return false;
        }
        private async Task<bool> FetterWard()
        {
            List<string> spells = new List<string> { ConjurerSpells.Repose.Name, ThaumaturgeSpells.Sleep.Name };

            var unit = (from a in GameObjectManager.GetObjectsOfType<BattleCharacter>()
                        where a.CanAttack
                        where a.CurrentTargetId == Core.Player.ObjectId
                        where a.IsCasting && spells.Contains(a.SpellCastInfo.SpellData.Name)
                        select a).FirstOrDefault();


            if (unit != null)
            {
                await MonkSpells.PvP.FetterWard.Buff();
            }
            {
                return false;
            }
        }
        #endregion
        #endregion
    }
}
